package com.qianfeng.Event.listener;

import com.qianfeng.Event.LoginEvent;
import com.qianfeng.Event.LoginFailEvent;
import com.qianfeng.pojo.BaseUser;
import com.qianfeng.pojo.SysLogininfor;
import com.qianfeng.pojo.SysUserOnline;
import com.qianfeng.service.LoginLogService;
import com.qianfeng.service.OnLineUserService;
import com.qianfeng.service.UserService;
import com.qianfeng.utils.RequestUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.event.AuthorizationFailureEvent;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/*
 *@Description:事件
 *@author:刘哥
 *@Date:86180 2022/9/5 20:03
 */

@Component
public class LoginEventListener {
//    创建线程池
    private TaskExecutor taskExecutor;
    @Autowired
    public void setTaskExecutor(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    private OnLineUserService onLineUserService;
    @Autowired
    public void setOnLineUserService(OnLineUserService onLineUserService) {
        this.onLineUserService = onLineUserService;
    }

    private LoginLogService loginLogService;
    @Autowired
    public void setLoginLogService(LoginLogService loginLogService) {
        this.loginLogService = loginLogService;
    }

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

//    @Async//开启事件异步处理
    @EventListener//开启事件监听
    public void onEvent(AuthenticationSuccessEvent event) {
        String username = ((BaseUser) event.getAuthentication().getPrincipal()).getUsername();
        Long UserId = ((BaseUser) event.getAuthentication().getPrincipal()).getUserId();
        System.out.println(Thread.currentThread().getName());//确认是否是异步
//        获取请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //根据请求头user-agent获取用户的浏览器,操作系统  RequestUtil自己创建的方法类
        Map<String, String> osAndBrowserInfo = RequestUtil.getOsAndBrowserInfo(request);
        String sessionId = request.getSession().getId();
        String ip = request.getRemoteHost();

//        执行异步线程,修改登录时间和ip
        CompletableFuture.runAsync(() -> {
            userService.updateLoginData(UserId,ip);
        }, taskExecutor);
//        在开启一个异步线程修改系统和浏览器信息
        CompletableFuture.runAsync(()->{
//            封装用户的日志信息
            SysLogininfor sysLogininfor=addLog(osAndBrowserInfo,ip,username);
            sysLogininfor.setStatus("1");
            sysLogininfor.setMsg("登录成功");
//            获取在线对象日志信息并添加到在线用户中中
            loginLogService.addLog(sysLogininfor);

            //获取系统和浏览器信息
            String os=osAndBrowserInfo.get("os");
            String browser = osAndBrowserInfo.get("browser");
            System.out.println("osAndBrowserInfo = " + osAndBrowserInfo);
            System.out.println("os = " + os);
            System.out.println("browser = " + browser);

//            TODO 将数据插入到数据库,注意,理论上一个用户名应该只有一行数据
            SysUserOnline sysUserOnline = new SysUserOnline();
            sysUserOnline.setSessionId(sessionId);
            sysUserOnline.setLoginName(username);
            sysUserOnline.setIpaddr(ip);
            //设置登录地址,用上面的登录日志中的数据来设置
            sysUserOnline.setLoginLocation(sysLogininfor.getLoginLocation());
            sysUserOnline.setBrowser(browser);
            sysUserOnline.setOs(os);
            sysUserOnline.setStatus("1");
            sysUserOnline.setStartTimestamp(new Date());
            sysUserOnline.setLastAccessTime(new Date());
            sysUserOnline.setExpireTime(30L);
            onLineUserService.addOnLineData(sysUserOnline);

        },taskExecutor);//用于完成异步执行的执行器
    }
    @EventListener
    public void onLoginFail(AuthorizationFailureEvent event){
        String username = (String) event.getAuthentication().getPrincipal();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        获取浏览器和系统信息
        Map<String, String> osAndBrowserInfo = RequestUtil.getOsAndBrowserInfo(request);
//        获取ip地址
        String ip = request.getRemoteHost();
        CompletableFuture.runAsync(()->{
            SysLogininfor sysLogininfor = addLog(osAndBrowserInfo, ip,username);
            sysLogininfor.setStatus("0");
            sysLogininfor.setMsg("登录失败");
            loginLogService.addLog(sysLogininfor);
        },taskExecutor);
    }

    private SysLogininfor addLog(Map<String, String> osAndBrowserInfo, String ip, String username) {
        String os=osAndBrowserInfo.get("os");
        String browser = osAndBrowserInfo.get("browser");
        System.out.println("os = " + os);
        System.out.println("browser = " + browser);
//        格局皮获取地址
        String locationByIp = RequestUtil.getLocationByIp(ip);
//        String locationByIp="局域网地址";
        SysLogininfor sysLogininfor=new SysLogininfor();
        sysLogininfor.setLoginLocation(locationByIp);
        sysLogininfor.setLoginName(username);
        sysLogininfor.setIpaddr(ip);
        sysLogininfor.setOs(os);
        sysLogininfor.setBrowser(browser);
        sysLogininfor.setLoginTime(new Date());
        return sysLogininfor;
    }


}